home *** CD-ROM | disk | FTP | other *** search
/ Aminet 6 / Aminet 6 - June 1995.iso / Aminet / game / think / Dragon.lha / Dragon / Source / DragDisp.c next >
Encoding:
C/C++ Source or Header  |  1994-07-02  |  18.1 KB  |  657 lines

  1. /************************************************************************
  2. *                                                                        *
  3. * Display functions for Dragon game.                                    *
  4. *                                                                        *
  5. *                        Copyright ©1994 Nick Christie                    *
  6. *                                                                        *
  7. *************************************************************************/
  8.  
  9. /************************************************************************
  10. ******************************  INCLUDES  *******************************
  11. *************************************************************************/
  12.  
  13. #include "DragonDefs.h"
  14. #include "Dragon.h"
  15.  
  16. #define READBUFSIZE        8192
  17.  
  18. /************************************************************************
  19. *************************  EXTERNAL REFERENCES  *************************
  20. *************************************************************************/
  21.  
  22. extern UWORD TopLevelTile(BOARD board,UWORD x,UWORD y);
  23. extern BOOL  CanMoveTile(BOARD board,UWORD x,UWORD y,UWORD z);
  24.  
  25. extern struct RastPort    *BufRPort;
  26. extern UWORD             PairsLeft;
  27. extern struct ColorSpec ScrnClrs[];
  28.  
  29. /************************************************************************
  30. *****************************  PROTOTYPES  ******************************
  31. *************************************************************************/
  32.  
  33. BOOL OpenBufRPort(void);
  34. void CloseBufRPort(void);
  35.  
  36. void LoadBackground(char *fname);
  37. void UnloadBackground(void);
  38.  
  39. BOOL LoadTileImages(char *fname);
  40. void UnloadTileImages(void);
  41.  
  42. BOOL LoadILBM(char *fname,UBYTE *dest,UBYTE *cmap,
  43.     UWORD width,UWORD height,UBYTE depth);
  44. BOOL ReadBODY(struct IFFHandle *iff,UBYTE *destmem,
  45.     UWORD width,UWORD height,UBYTE depth);
  46. BOOL UnPackRow(struct IFFHandle *iff,UBYTE *dst,ULONG dstlen);
  47.  
  48. BOOL InitReadBuf(void);
  49. void CloseReadBuf(void);
  50. BOOL ReadBufByte(struct IFFHandle *iff,UBYTE *buf);
  51.  
  52. void DrawBoard(BOARD board,struct RastPort *rp);
  53. void DrawOneTile(UBYTE tile,struct RastPort *rp,UWORD x,UWORD y);
  54. void DisplayStats(BOARD board,struct RastPort *rp);
  55. UWORD PossibleMoves(BOARD board);
  56. void SelectStats(UBYTE tile,BOARD board,struct RastPort *rp);
  57.  
  58. /************************************************************************
  59. ********************************  DATA  *********************************
  60. *************************************************************************/
  61.  
  62. /*
  63.  * All the drawing takes place off-screen in an allocated rastport,
  64.  * to which this points. It gets a bitmap attached to it.
  65.  */
  66.  
  67. struct RastPort    *BufRPort = NULL;
  68.  
  69. /*
  70.  * This is the image structure used for filling in the background.
  71.  * The boolean indicates if the background image was loaded okay.
  72.  */
  73.  
  74. BOOL BgndOkay = FALSE;
  75.  
  76. struct Image BgndImage = {
  77.         0, 0, 320, 256, 4, NULL, 0x0f, 0x10, NULL
  78. };
  79.  
  80. /*
  81.  * Here's where we keep a pointer to the chip mem allocated for
  82.  * storing the tile images. These are loaded on startup. Also here
  83.  * is a bitmap structure, which we fill in.
  84.  */
  85.  
  86. UBYTE            *TileImages = 0;
  87. struct BitMap    TileImageBitMap;
  88.  
  89. /************************************************************************
  90. ***************************  OPENBUFRPORT()  ****************************
  91. *************************************************************************
  92. * Creates & initializes the buffer rastport, used for drawing into so that
  93. * updates are invisible.
  94. *
  95. *************************************************************************/
  96.  
  97. BOOL OpenBufRPort(void)
  98. {
  99. UWORD    i = 0;
  100. BOOL    okay = TRUE;
  101.  
  102. if (BufRPort = (struct RastPort *) AllocMem(
  103.                     sizeof(struct RastPort),MEMF_PUBLIC|MEMF_CLEAR))
  104.     {
  105.     InitRastPort(BufRPort);
  106.     if (BufRPort->BitMap = (struct BitMap *) AllocMem(
  107.                     sizeof(struct BitMap),MEMF_PUBLIC|MEMF_CLEAR))
  108.         {
  109.         InitBitMap(BufRPort->BitMap,SCRDEPTH,SCRWIDTH,SCRHEIGHT);
  110.  
  111.         for(i=0; i<SCRDEPTH && okay; i++)
  112.             {
  113.             if (!(BufRPort->BitMap->Planes[i] = AllocRaster(
  114.                     SCRWIDTH,SCRHEIGHT))) okay = FALSE;
  115.             }
  116.         }
  117.     else
  118.         okay = FALSE;
  119.     }
  120. else
  121.     okay = FALSE;
  122.  
  123. return(okay);
  124. }
  125.  
  126. /************************************************************************
  127. ***************************  CLOSEBUFRPORT()  ***************************
  128. *************************************************************************
  129. * Releases any resources allocated by OpenBufRPort(), if any.
  130. *
  131. *************************************************************************/
  132.  
  133. void CloseBufRPort(void)
  134. {
  135. PLANEPTR p;
  136. UWORD     i;
  137.  
  138. if (BufRPort)
  139.     {
  140.     if (BufRPort->BitMap)
  141.         {
  142.         for(i=0;i<SCRDEPTH;i++)
  143.             {
  144.             if (p = BufRPort->BitMap->Planes[i])
  145.                 FreeRaster(p,SCRWIDTH,SCRHEIGHT);
  146.             }
  147.         FreeMem((APTR)BufRPort->BitMap,sizeof(struct BitMap));
  148.         }
  149.     FreeMem((APTR)BufRPort,sizeof(struct RastPort));
  150.     }
  151. }
  152.  
  153. /************************************************************************
  154. ***************************  LOADBACKGROUND() ***************************
  155. *************************************************************************
  156. * Tries the load the named background picture (an IFF ILBM). This must be
  157. * 320*256*4 and be compressed with ByteRun1. It will be blitted each
  158. * time the board is drawn (behind the tiles) into bps 1-4 of the screen.
  159. * Screen colour pens 20-31 are set to those in pens 4-15 of the image.
  160. * If the file can't be loaded for any reason, no error is returned, but
  161. * BgndOkay will be FALSE and no background will be rendered. Only the
  162. * bitplane memory is allocated, no other system structures.
  163. *
  164. *************************************************************************/
  165.  
  166. void LoadBackground(char *fname)
  167. {
  168. UBYTE    *bgnddata,*creg,colourmap[32*3];
  169. UWORD    pen;
  170.  
  171. if (!(bgnddata = AllocMem(320*256*4/8,MEMF_CHIP|MEMF_PUBLIC)))
  172.     return;
  173.  
  174. BgndImage.ImageData = (UWORD *) bgnddata;
  175.  
  176. if (LoadILBM(fname,bgnddata,colourmap,320,256,4))
  177.     {
  178.     BgndOkay = TRUE;
  179.  
  180.     creg = &colourmap[4*sizeofColorRegister];
  181.  
  182.     for(pen=20;pen<32;pen++)
  183.         {
  184.         ScrnClrs[pen].Red = *creg++;
  185.         ScrnClrs[pen].Green = *creg++;
  186.         ScrnClrs[pen].Blue = *creg++;
  187.         }
  188.     }
  189. }
  190.  
  191. /************************************************************************
  192. *************************  UNLOADBACKGROUND()  **************************
  193. *************************************************************************
  194. * Release all resources allocated by LoadBackground(), if any. This will
  195. * only be the image data.
  196. *
  197. *************************************************************************/
  198.  
  199. void UnloadBackground(void)
  200. {
  201. if (BgndImage.ImageData) FreeMem((UBYTE *)BgndImage.ImageData,320*256*4/8);
  202. }
  203.  
  204. /************************************************************************
  205. **************************  LOADTILEIMAGES()  ***************************
  206. *************************************************************************
  207. * Load the named IFF ILBM file containing the tile images into some
  208. * allocated bitplane memory. This must be a 320*96*4 brush, with the
  209. * tiles laid out in a particular fashion. See "Template.pic" for the
  210. * correct positions. It should be saved with ByteRun1 compression.
  211. * We initialize a bitmap structure here for it, so that we can blit
  212. * the individual tile images around. Colours 2-15 in the screen are
  213. * set to those of the tiles.
  214. *
  215. *************************************************************************/
  216.  
  217. BOOL LoadTileImages(char *fname)
  218. {
  219. UBYTE    *planeptr,*creg,colourmap[32*3];
  220. UWORD    i;
  221.  
  222. if (!(TileImages = AllocMem(320*96*4/8,MEMF_CHIP|MEMF_PUBLIC)))
  223.     return(FALSE);
  224.  
  225. InitBitMap(&TileImageBitMap,4,320,96);
  226.  
  227. planeptr = TileImages;
  228. for(i=0;i<4;i++)
  229.     {
  230.     TileImageBitMap.Planes[i] = (PLANEPTR) planeptr;
  231.     planeptr += 320*96/8;
  232.     }
  233.  
  234. if (LoadILBM(fname,TileImages,colourmap,320,96,4))
  235.     {
  236.     creg = &colourmap[2*sizeofColorRegister];
  237.  
  238.     for(i=2;i<16;i++)
  239.         {
  240.         ScrnClrs[i].Red = *creg++;
  241.         ScrnClrs[i].Green = *creg++;
  242.         ScrnClrs[i].Blue = *creg++;
  243.         }
  244.  
  245.     return(TRUE);
  246.     }
  247.  
  248. return(FALSE);
  249. }
  250.  
  251. /************************************************************************
  252. *************************  UNLOADTILEIMAGES()  **************************
  253. *************************************************************************
  254. * Release whatever LoadTileImages() got, if anything.
  255. *
  256. *************************************************************************/
  257.  
  258. void UnloadTileImages(void)
  259. {
  260. if (TileImages) FreeMem((UBYTE *)TileImages,320*96*4/8);
  261. }
  262.  
  263. /************************************************************************
  264. *****************************  LOADILBM()  ******************************
  265. *************************************************************************
  266. * Read the ILBM file, name supplied, into the destination bitplanes
  267. * supplied (they must be a contiguous block), with the given width,
  268. * height and depth. The colourmap chunk is copied to the buffer supplied
  269. * for the purpose, which must be large enough for 32 pens. The RGB
  270. * values are right-shifted before copying. The ILBM must be ByteRun1
  271. * compressed.
  272. *
  273. *************************************************************************/
  274.  
  275. BOOL LoadILBM(char *fname,UBYTE *dest,UBYTE *cmap,
  276.     UWORD width,UWORD height,UBYTE depth)
  277. {
  278. struct IFFHandle        *iff;
  279. struct StoredProperty    *prop;
  280. BitMapHeader            *bmhd;
  281. UBYTE                    *creg;
  282. UWORD                    i;
  283. BOOL                    okay = FALSE;
  284.  
  285. if (iff = AllocIFF())
  286.     {
  287.     if (iff->iff_Stream = Open(fname,MODE_OLDFILE))
  288.         {
  289.         InitIFFasDOS(iff);
  290.         if (OpenIFF(iff,IFFF_READ) == 0)
  291.             {
  292.             if (PropChunk(iff,ID_ILBM,ID_BMHD)) goto abortiff;
  293.             if (PropChunk(iff,ID_ILBM,ID_CMAP)) goto abortiff;
  294.             if (StopChunk(iff,ID_ILBM,ID_BODY)) goto abortiff;
  295.             if (ParseIFF(iff,IFFPARSE_SCAN)) goto abortiff;
  296.  
  297.             if (!(prop = FindProp(iff,ID_ILBM,ID_BMHD))) goto abortiff;
  298.  
  299.             bmhd = (BitMapHeader *) prop->sp_Data;
  300.  
  301.             if ((bmhd->w != width) || (bmhd->h != height) ||
  302.                 (bmhd->nPlanes != depth) || (bmhd->compression != cmpByteRun1))
  303.                 goto abortiff;
  304.  
  305.             if (!(prop = FindProp(iff,ID_ILBM,ID_CMAP))) goto abortiff;
  306.  
  307.             creg = (UBYTE *) prop->sp_Data;
  308.  
  309.             for(i=0; i<prop->sp_Size; i++)
  310.                 *cmap++ = *creg++ >> 4;
  311.  
  312.             okay = ReadBODY(iff,dest,width,height,depth);
  313.  
  314. abortiff:
  315.  
  316.             CloseIFF(iff);
  317.             }
  318.         Close(iff->iff_Stream);
  319.         }
  320.     FreeIFF(iff);
  321.     }
  322.  
  323. return(okay);
  324. }
  325.  
  326. /************************************************************************
  327. *****************************  READBODY()  ******************************
  328. *************************************************************************
  329. * Read the BODY from the IFFHandle, where it has stopped, putting the
  330. * data in the given bitplane memory. We are given the dimensions to
  331. * expect, and can assume that the destination memory is large enough for
  332. * all the contiguous bitplane data. We can also assume ByteRun1.
  333. *
  334. *************************************************************************/
  335.  
  336. BOOL ReadBODY(struct IFFHandle *iff,UBYTE *destmem,
  337.     UWORD width,UWORD height,UBYTE depth)
  338. {
  339. ULONG    rastoff,rastsize;
  340. UWORD    bytesprow;
  341. UBYTE    *planptr,*destptr,plane;
  342.  
  343. if (!InitReadBuf()) return(FALSE);
  344.  
  345. bytesprow = width >> 3;
  346. rastsize = bytesprow * height;
  347.  
  348. for (rastoff=0; rastoff<rastsize; rastoff+=bytesprow)
  349.     {
  350.     planptr = destmem;
  351.     for (plane=0; plane<depth; plane++)
  352.         {
  353.         destptr = planptr + rastoff;
  354.         planptr += rastsize;
  355.         if (!UnPackRow(iff,destptr,bytesprow))
  356.             {
  357.             CloseReadBuf();
  358.             return(FALSE);
  359.             }
  360.         }
  361.     }
  362.  
  363. CloseReadBuf();
  364.  
  365. return(TRUE);
  366. }
  367.  
  368. /************************************************************************
  369. *****************************  UNPACKROW()  *****************************
  370. *************************************************************************
  371. * Unpack byterun1 compressed bytes from iff handle to dest until dstlen
  372. * bytes written. Returns false on error. Compression consists of
  373. * control byte followed by one or more data bytes as follows :-
  374. *     n = 0 to 127    copy following n+1 bytes literally.
  375. *     n = -1 to -127    replicate following byte (-n)+1 times.
  376. *     n = -128        do nothing.
  377. *
  378. **************************************************************************/
  379.  
  380. BOOL UnPackRow(struct IFFHandle *iff,UBYTE *dst,ULONG dstlen)
  381. {
  382. ULONG    written;
  383. UBYTE    ctrl,data;
  384.  
  385. written = 0;
  386.  
  387. while (written != dstlen)
  388.     {
  389.     if (!ReadBufByte(iff,&ctrl)) return(FALSE);
  390.  
  391.     if (ctrl != 0x80)                    /* not a NOP */
  392.         {
  393.         if (ctrl & 0x80)                /* replicate run */
  394.             {
  395.             ctrl = ~ctrl + 2;            /* ctrl = (-ctrl) + 1 */
  396.             if (!ReadBufByte(iff,&data)) return(FALSE);
  397.             do
  398.                 {
  399.                 if (++written > dstlen) return(FALSE);
  400.                 *dst++ = data;
  401.                 }
  402.             while (--ctrl != 0);
  403.             }
  404.         else                            /* literal run */
  405.             {
  406.             ctrl++;
  407.             do
  408.                 {
  409.                 if (++written > dstlen) return(FALSE);
  410.                 if (!ReadBufByte(iff,dst++)) return(FALSE);
  411.                 }
  412.             while (--ctrl != 0);
  413.             }
  414.  
  415.         } /* endif not NOP */
  416.     } /* endwhile written != dstlen */
  417.  
  418. return(TRUE);
  419. }
  420.  
  421. /************************************************************************
  422. ****************************  INITREADBUF()  ****************************
  423. *************************************************************************
  424. * Allocate a read buffer and initialize it. Return false on failure.
  425. *
  426. *************************************************************************/
  427.  
  428. UBYTE    *ReadBuf;
  429. ULONG    BufBytes,BufOffset;
  430.  
  431. BOOL InitReadBuf(void)
  432. {
  433. if (!(ReadBuf = AllocMem(READBUFSIZE,MEMF_PUBLIC))) return(FALSE);
  434. BufOffset = BufBytes = 0;
  435. return(TRUE);
  436. }
  437.  
  438. /************************************************************************
  439. ***************************  CLOSEREADBUF()  ****************************
  440. *************************************************************************
  441. * Free the read buffer previously succesfully alloc'd by InitReadBuf().
  442. * Do NOT call if Init() failed.
  443. *
  444. *************************************************************************/
  445.  
  446. void CloseReadBuf(void)
  447. {
  448. FreeMem(ReadBuf,READBUFSIZE);
  449. }
  450.  
  451. /************************************************************************
  452. ****************************  READBUFBYTE()  ****************************
  453. *************************************************************************
  454. * Return the next byte from the read buffer, re-filling it if necessary,
  455. * and returning an error BOOL. EOF is treated as error.
  456. *
  457. *************************************************************************/
  458.  
  459. BOOL ReadBufByte(struct IFFHandle *iff,UBYTE *buf)
  460. {
  461. LONG actual;
  462.  
  463. if (BufBytes == 0)
  464.     {
  465.     actual = ReadChunkBytes(iff,ReadBuf,READBUFSIZE);
  466.     if (actual <= 0) return(FALSE);
  467.     BufBytes = actual;
  468.     BufOffset = 0;
  469.     }
  470.  
  471. *buf = ReadBuf[BufOffset++];
  472. BufBytes--;
  473.  
  474. return(TRUE);
  475. }
  476.  
  477. /************************************************************************
  478. *****************************  DRAWBOARD()  *****************************
  479. *************************************************************************
  480. * Take a tile array and a rastport & draw the tile graphics into it.
  481. * The graphics are initially drawn in the buffer rastport, then blitted
  482. * across.
  483. *
  484. *************************************************************************/
  485.  
  486. void DrawBoard(BOARD board,struct RastPort *rp)
  487. {
  488. UWORD        i,j,k;
  489. UWORD        sx,sy,x,y;
  490. UBYTE        t;
  491.  
  492. if (BgndOkay)
  493.     DrawImage(BufRPort,&BgndImage,0,0);
  494. else
  495.     SetRast(BufRPort,0);
  496.  
  497. sx = BRDLEFTEDGE; sy = BRDTOPEDGE;
  498.  
  499. for(i=0;i<BOARDZ;i++)
  500.     {
  501.     y = sy;
  502.     for(j=0;j<BOARDY;j++)
  503.         {
  504.         x = sx;
  505.         for(k=0;k<BOARDX;k++)
  506.             {
  507.             if (t = board[i][j][k]) DrawOneTile(t,BufRPort,x,y);
  508.             x += TILEXSPACE;
  509.             }
  510.         y += TILEYSPACE;
  511.         }
  512.     sx -= LEVELXADJ;
  513.     sy -= LEVELYADJ;
  514.     }
  515.  
  516. DisplayStats(board,BufRPort);
  517.  
  518. BltBitMapRastPort(BufRPort->BitMap,0,0,rp,0,0,
  519.                     SCRWIDTH,SCRHEIGHT,0xc0);
  520.  
  521. }
  522.  
  523. /************************************************************************
  524. ****************************  DRAWONETILE()  ****************************
  525. *************************************************************************
  526. * Draw the image corresponding to the given tile ID code into the given
  527. * rastport at the given x,y location.
  528. *
  529. *************************************************************************/
  530.  
  531. void DrawOneTile(UBYTE tile,struct RastPort *rp,UWORD x,UWORD y)
  532. {
  533. UWORD    bmx,bmy;
  534.  
  535. bmx = ((tile-1) % 10) * 32;
  536. bmy = ((tile-1) / 10) * 32;
  537.  
  538. BltBitMapRastPort(&TileImageBitMap,bmx,bmy,rp,x,y,
  539.                     TILEWIDTH,TILEHEIGHT,0xc0);
  540. SetAPen(rp,0);
  541. SetDrMd(rp,JAM1);
  542. rp->Mask = 16;
  543. RectFill(rp,x,y,x+TILEWIDTH-1,y+TILEHEIGHT-1);
  544. rp->Mask = 255;
  545.  
  546. }
  547.  
  548. /************************************************************************
  549. ***************************  DISPLAYSTATS()  ****************************
  550. *************************************************************************
  551. * Display the statistics for # tiles left & # moves possible in the
  552. * supplied rastport. Also prepare the area in which we will display the
  553. * pairs remaining of the selected type (when one gets selected).
  554. *
  555. *************************************************************************/
  556.  
  557. void DisplayStats(BOARD board,struct RastPort *rp)
  558. {
  559. char    strbuf[4];
  560. UWORD    possible;
  561.  
  562. SetDrMd(rp,JAM1);
  563. SetOPen(rp,1);
  564. SetAPen(rp,0);
  565. RectFill(rp,6,165,27,177);
  566. RectFill(rp,290,115,311,129);
  567. RectFill(rp,290,145,311,159);
  568. BNDRYOFF(rp);
  569. SetAPen(rp,1);
  570.  
  571. sprintf(strbuf,"%2d",PairsLeft);
  572. Move(rp,293,125);
  573. Text(rp,strbuf,2);
  574.  
  575. possible = PossibleMoves(board);
  576. sprintf(strbuf,"%2d",possible);
  577. Move(rp,293,155);
  578. Text(rp,strbuf,2);
  579. }
  580.  
  581. /************************************************************************
  582. ***************************  POSSIBLEMOVES()  ***************************
  583. *************************************************************************
  584. * Calculate the number of tiles that can be moved in the given board.
  585. *
  586. *************************************************************************/
  587.  
  588. UWORD PossibleMoves(BOARD board)
  589. {
  590. UWORD    x,y,z;
  591. UBYTE    histo[MAXTILETYPE+1],t;
  592.  
  593. memset(histo,0,MAXTILETYPE+1);
  594.  
  595. for(y=0;y<BOARDY;y++)
  596.     {
  597.     for(x=0;x<BOARDX;x++)
  598.         {
  599.         z = TopLevelTile(board,x,y);
  600.         if (t = board[z][y][x])
  601.             {
  602.             if (CanMoveTile(board,x,y,z)) histo[t]++;
  603.             }
  604.         }
  605.     }
  606.  
  607. for(x=0,t=1; t<MAXTILETYPE+1; t++) x += histo[t] / 2;
  608.  
  609. return(x);
  610. }
  611.  
  612. /************************************************************************
  613. ****************************  SELECTSTATS()  ****************************
  614. *************************************************************************
  615. * Display statistics on the newly selected tile. This shows how many pairs
  616. * of that type still remain on the board, and whether any can be removed.
  617. * An area for the display has already been prepared with DisplayStats().
  618. *
  619. *************************************************************************/
  620.  
  621. void SelectStats(UBYTE tile,BOARD board,struct RastPort *rp)
  622. {
  623. UWORD    x,y,z;
  624. UBYTE    tcnt = 0, mcnt = 0;
  625. char    cbuf[2];
  626.  
  627. for(z=0;z<BOARDZ;z++)
  628.     {
  629.     for(y=0;y<BOARDY;y++)
  630.         {
  631.         for(x=0;x<BOARDX;x++)
  632.             {
  633.             if (board[z][y][x] == tile)
  634.                 {
  635.                 tcnt++;
  636.                 if (TopLevelTile(board,x,y) == z)
  637.                     {
  638.                     if (CanMoveTile(board,x,y,z)) mcnt++;
  639.                     }
  640.                 }
  641.             }
  642.         }
  643.     }
  644.  
  645.  
  646. cbuf[0] = (mcnt > 1) ? '*' : ' ';
  647. cbuf[1] = (tcnt / 2) + '0';
  648.  
  649. SetDrMd(rp,JAM2);
  650. SetAPen(rp,1);
  651. SetBPen(rp,0);
  652. Move(rp,9,174);
  653. Text(rp,cbuf,2);
  654. }
  655.  
  656.  
  657.